package com.handler.utils;

import com.to.FileReq;
import com.to.MetaInfo;
import io.netty.buffer.ByteBuf;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class FileWriter implements Runnable {

    private final BlockingQueue<FileReq> fileReqs;

    private final Map<String, OutputStream> fileNameMappingOutputStream = new ConcurrentHashMap<>();

    private final byte[] cache = new byte[1024];

    public FileWriter(BlockingQueue<FileReq> fileReqs) {

        this.fileReqs = fileReqs;
    }

    @Override
    public void run() {
        try {
            while (true) {

//                从阻塞队列中取出 数据包
//                然后将其写入硬盘
                FileReq fileReq = fileReqs.take();

                MetaInfo metaInfo = fileReq.getMetaInfo();
                ByteBuf buf = fileReq.getFile();

                String fileName = metaInfo.getPath() + metaInfo.getFileName();

                OutputStream output = fileNameMappingOutputStream.computeIfAbsent(fileName, fileName2 -> {
                    try {
                        return new BufferedOutputStream(new FileOutputStream(fileName2, true));
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                    }
                });


                log.info("正在写入偏移量为{}的数据", metaInfo.getContinueTransportOffset());
                while (buf.isReadable()) {
                    int readLength = Math.min(buf.readableBytes(), 1024);
                    buf.readBytes(cache, 0, readLength);
                    output.write(cache, 0, readLength);
                }

                log.info("偏移量为{}的数据已写入完成", metaInfo.getContinueTransportOffset());
                buf.release();

                if (metaInfo.isDone()) {
                    fileNameMappingOutputStream.remove(fileName);
                    log.info("{}已写入完成",fileName);
                    output.close();
                }
            }
        } catch (InterruptedException | IOException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }

    }
}
